package org.tinygame.herostory;

import com.google.protobuf.GeneratedMessageV3;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.tinygame.herostory.cmdHandler.CmdHandlerFactory;
import org.tinygame.herostory.cmdHandler.ICmdHandler;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**主线程处理器
 * @author shkstart
 * @create 2022-05-07 9:49
 */
public final class MainThreadProcessor {
    //日志
    private static final Logger LOGGER= LoggerFactory.getLogger(MainThreadProcessor.class);

    private MainThreadProcessor(){}

    /**
     * 单例对象
     */
    private static final MainThreadProcessor _instance=new MainThreadProcessor();

    /**
     * 创建一个单线程
     */
    private final ExecutorService _es= Executors.newSingleThreadExecutor((r)-> {
        Thread newThread=new Thread(r);
        newThread.setName("MainThreadProcessor");
        return newThread;
    });

    /**
     * 获取单例对象
     * @return
     */
    public static MainThreadProcessor GetInstance(){
        return _instance;
    }

    /**
     * 处理消息
     * @param ctx 客户端信道
     * @param msg 消息对象
     */
    public void process(ChannelHandlerContext ctx, GeneratedMessageV3 msg){
        if(null==ctx||null==msg){
            return;
        }

        //获取消息类型
        Class<?> msgClazz=msg.getClass();

        LOGGER.info(
                "收到客户端消息, msgClazz = {}",
                msgClazz.getName()
        );
        //这里线程为nioEventLoopGroup
        //LOGGER.info("程序线程为：{}",Thread.currentThread().getName());

        //nioEventLoopGroup线程，将操作提交到MainThreadProcessor线程中等待执行
        this._es.submit(()->{

            //获取指令处理器
            ICmdHandler<? extends GeneratedMessageV3> cmdHandler= CmdHandlerFactory.create(msgClazz);

            if(null==cmdHandler){
                LOGGER.error("未找到相对应的指令处理器，msgClazz={}",msgClazz.getName());
                return;
            }

            try {
                //处理指令
                cmdHandler.handle(ctx,cast(msg));
            } catch (Exception ex) {
                LOGGER.error(ex.getMessage(),ex);
            }
        });

    }

    /**
     *  处理消息
     * @param r Runnable实例
     */
    public void process(Runnable r){
        if(null!=r){
            _es.submit(r);
        }
    }
    /**
     * 转型消息对象
     * @param msg 消息对象
     * @param <TCmd> 指令类型
     * @return
     */
    private static <TCmd extends GeneratedMessageV3> TCmd cast(Object msg){
        if(null==msg){
            return null;
        }else{
            return (TCmd) msg;
        }
    }
}
